
/*
Log默认输出到控制台和调试输出窗口, 不输出到文件
宏开关
LOG_TO_FILE			字符串, log文件名
LOG_TO_CONSOLE		布尔型, 是否输出到console
LOG_TO_DEBUG	布尔型, 是否输出到调试输出窗口(outputdebugstring)
例如:
	#define LOG_TO_FILE	 "d:/a.txt"	//输出到文件a.txt
	#define LOG_TO_CONSOLE	 false		// 不输出到控制台
	#define LOG_TO_DEBUG true		//输出到调试输出窗口

	
*/

#pragma  once
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>

#include "String.h"

using namespace std;



#define __SIMPLE_LOG__
//#define LOG_TO_FILE "d:/test/a.txt"

//以系统编码(GetACP()) 写入到文件/标准输出/OutputDebugWindow
//要写入UTF-8字符串, 需要调用Append(str, CP_UTF8)
class Logger{
public:
	static Logger& get(int level = 0);
	static void SetLogFile(string logfile);
	static void SetToConsole(bool toConsole);
	static void SetToDebugWindow(bool toDebugWindow);
private:
	static bool toConsole;
	static bool toDebugWindow;
	static string filename;
private:
	Logger(string filename = "", bool toConsole = true, bool toDebugWindow = true);
public:
	void Append(const string& s, UINT cp = GetACP());
	void Append(const wstring& ws);
	size_t Length()const ;
	void Flush();
protected:
	string buf;
};


Logger& operator << (Logger& slog, Logger& (*pFun)(Logger&) );
Logger& Timestamp(Logger& slog);
Logger& ThreadID(Logger& slog);
Logger& endl(Logger& slog);
Logger& flush(Logger& slog);

//内置类型
Logger& operator << (Logger& slog, bool val);
Logger& operator << (Logger& slog, char val);
Logger& operator << (Logger& slog, unsigned char val);
Logger& operator << (Logger& slog, short val);
Logger& operator << (Logger& slog, unsigned short val);
Logger& operator << (Logger& slog, wchar_t val);//vs 默认视wchar_t为内置类型!!
Logger& operator << (Logger& slog, int val);
Logger& operator << (Logger& slog, unsigned int val);
Logger& operator << (Logger& slog, long val);
Logger& operator << (Logger& slog, unsigned long val);
Logger& operator << (Logger& slog, float val);
Logger& operator << (Logger& slog, double val);
Logger& operator << (Logger& slog, long double val);
//字符串
Logger& operator << (Logger& slog, char* s);
Logger& operator << (Logger& slog, wchar_t* ws);
Logger& operator << (Logger& slog, const char* s);
Logger& operator << (Logger& slog, const wchar_t* ws);
//标准库字符串
Logger& operator << (Logger& slog, string& s);
Logger& operator << (Logger& slog, wstring& ws);
Logger& operator << (Logger& slog, const string& s);
Logger& operator << (Logger& slog, const wstring& ws);



//标准库 容器

////vector
//template<typename T>
//Logger& operator <<(Logger& slog, vector<T>& val){
//	slog<<"vector:[";
//	vector<T>::const_iterator it;
//	for(it = val.begin(); it != val.end(); ++it){
//		if(it != val.begin()){
//			slog<<", ";
//		}
//		slog<<(*it);
//	}
//	slog<<"] ";
//	return slog;
//}
template<typename T>
Logger& operator << (Logger& slog, const vector<T>& val){
	return operator <<(slog, const_cast<vector<T>&>(val));
}


////map
//template<typename K, typename V>
//Logger& operator << (Logger& slog, map<K, V>& val){
//	slog<<"map:[";
//	map<K, V>::const_iterator it;
//	for(it = val.begin(); it != val.end(); ++it){
//		if(it != val.begin()){
//			slog<<", ";
//		}
//		slog<<"{"<<(it->first)<<":"<<(it->second)<<"}";
//	}
//	slog<<"] ";
//	return slog;
//}
template<typename K, typename V>
Logger& operator << (Logger& slog, const map<K, V>& val){
	return operator <<(slog, const_cast<map<K, V>&>(val));
}

//
////multimap
//template<typename K, typename V>
//Logger& operator << (Logger& slog, multimap<K, V>& val){
//	slog<<"multimap:[";
//	multimap<K, V>::const_iterator it;
//	for(it = val.begin(); it != val.end(); ++it){
//		if(it != val.begin()){
//			slog<<", ";
//		}
//		slog<<"{"<<(it->first)<<":"<<(it->second)<<"}";
//	}
//	slog<<"] ";
//	return slog;
//}
template<typename K, typename V>
Logger& operator << (Logger& slog, const multimap<K, V>& val){
	return operator <<(slog, const_cast<multimap<K, V>&>(val));
}


////set
//template<typename T>
//Logger& operator << (Logger& slog, set<T>& val){
//	slog<<"set:[";
//	set<T>::const_iterator it;
//	for(it = val.begin(); it != val.end(); ++it){
//		if(it != val.begin()){
//			slog<<", ";
//		}
//		slog<<(*it);
//	}
//	slog<<"] ";
//	return slog;
//}
template<typename T>
Logger& operator << (Logger& slog, const set<T>& val){
	return operator <<(slog, const_cast<set<T>&>(val));
}


////multiset
//template<typename T>
//Logger& operator << (Logger& slog, multiset<T>& val){
//	slog<<"multiset:[";
//	multiset<T>::const_iterator it;
//	for(it = val.begin(); it != val.end(); ++it){
//		if(it != val.begin()){
//			slog<<", ";
//		}
//		slog<<(*it);
//	}
//	slog<<"] ";
//	return slog;
//}
template<typename T>
Logger& operator << (Logger& slog, const multiset<T>& val){
	return operator <<(slog, const_cast<multiset<T>&>(val));
}


////queue
//template<typename T>
//Logger& operator << (Logger& slog, queue<T>& val){
//	slog<<"queue:[";
//	typedef queue<T>::container_type::const_iterator it;
//	for(it = val._Get_container().begin(); it != val._Get_container().end(); ++it){
//		if(it != val._Get_container().begin()){
//			slog<<", ";
//		}
//		slog<<(*it);
//	}
//	slog<<"] ";
//	return slog;
//}
template<typename T>
Logger& operator << (Logger& slog, const queue<T>& val){
	return operator <<(slog, const_cast<queue<T>&>(val));
}



////deque
//template<typename T>
//Logger& operator << (Logger& slog, deque<T>& val){
//	slog<<"deque:[";
//	deque<T>::const_iterator it;
//	for(it = val.begin(); it != val.end(); ++it){
//		if(it != val.begin()){
//			slog<<", ";
//		}
//		slog<<(*it);
//	}
//	slog<<"] ";
//	return slog;
//}
template<typename T>
Logger& operator << (Logger& slog, const deque<T>& val){
	return operator <<(slog, const_cast<deque<T>&>(val));
}


////stack
//template<typename T>
//Logger& operator << (Logger& slog, stack<T>& val){
//	slog<<"stack:[";
//	stack<T>::container_type::const_iterator it;
//	for(it = val._Get_container().begin(); it != val._Get_container().end(); ++it){
//		if(it != val._Get_container().begin()){
//			slog<<", ";
//		}
//		slog<<(*it);
//	}
//	slog<<"] ";
//	return slog;
//}
template<typename T>
Logger& operator << (Logger& slog, const stack<T>& val){
	return operator <<(slog, const_cast<stack<T>&>(val));
}




//普通对象

//可以输出一个对象
//如果这个对象存在公有(public)成员函数:
//		wstring ToUnicode()const;
//则会调用这个成员函数,
//否则, 输出对象的类名和地址.
template<typename T>
Logger& operator << (Logger& slog, T& val){
#ifdef _MSC_VER
	__if_exists(T::ToUnicode){
		slog<<val.ToUnicode();
	}
	__if_not_exists(T::ToUnicode){
		slog<<typeid(T).name()<<" (@"<<UINT(&val)<<")";
	}
#else
	slog<<typeid(T).name()<<" (@"<<UINT(&val)<<")";
#endif

	return slog;
}
template<typename T>
Logger& operator << (Logger& slog, const T& val){//
	return operator << (slog, const_cast<T&>(val) );
}

template<typename T>
Logger& operator << (Logger& slog, T* val){ //NO const T* val !!
#ifdef _MSC_VER
	__if_exists(T::ToUnicode){
		if(0 != val){
			slog<<val->ToUnicode();
		}else{
			slog<<typeid(val).name()<<" (@NULL)";
		}
	}
	__if_not_exists(T::ToUnicode){
		slog<<typeid(val).name()<<" (@"<<UINT(val)<<")";
	}
#else
	slog<<typeid(val).name()<<" (@"<<UINT(val)<<")";
#endif
	return slog;
}
template<typename T>
Logger& operator << (Logger& slog, const T* val){
	return operator<< (slog, const_cast<T*>(val));
}

#ifndef Log
#define Log Logger::get(0)
#endif

#ifndef LogI
#define LogI Logger::get(0)
#endif

#ifndef LogW
#define LogW Logger::get(1)
#endif

#ifndef LogE
#define LogE Logger::get(2)
#endif



